#if !PocketPC
// UsbEject version 1.0 March 2006
// written by Simon Mourier <email: simon [underscore] mourier [at] hotmail [dot] com>

using System;
using System.Text;
using System.Threading;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Security;
#if !PocketPC && Framework20
using Microsoft.Win32.SafeHandles;
using System.Runtime.ConstrainedExecution;
#endif

namespace GeoFramework.IO.Usb
{
    /// <summary>
    /// Represents a low-level Windows structure containing USB information
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    [SuppressUnmanagedCodeSecurity()]
    internal class SP_DEVINFO_DATA
    {
        internal int cbSize = Marshal.SizeOf(typeof(SP_DEVINFO_DATA));
        internal Guid classGuid = Guid.Empty; // temp
        internal int devInst; // dumy
        internal int reserved;
    }

    [StructLayout(LayoutKind.Sequential, Pack = 2)]
    internal struct SP_DEVICE_INTERFACE_DETAIL_DATA
    {
        internal int cbSize;
        internal short devicePath;
    }

    [StructLayout(LayoutKind.Sequential)]
    [SuppressUnmanagedCodeSecurity()]
    internal class SP_DEVICE_INTERFACE_DATA
    {
        internal int cbSize = Marshal.SizeOf(typeof(SP_DEVICE_INTERFACE_DATA));
        internal Guid interfaceClassGuid = Guid.Empty; // temp
        internal int flags;
        internal int reserved;
    }

#if !PocketPC && Framework20
    [SuppressUnmanagedCodeSecurity]
#endif
    internal 
#if Framework20
		static 
#else
		sealed
#endif	
		class NativeMethods
    {

#if !Framework20
        private NativeMethods()
        {
        }
#endif

        // from winuser.h
        internal const int WM_DEVICECHANGE = 0x0219;

        // from winbase.h
        internal const int INVALID_HANDLE_VALUE = -1;
        internal const int GENERIC_READ = unchecked((int)0x80000000);
        internal const int FILE_SHARE_READ = 0x00000001;
        internal const int FILE_SHARE_WRITE = 0x00000002;
        internal const int OPEN_EXISTING = 3;

        //[DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
        //internal static extern bool GetVolumeNameForVolumeMountPoint(
        //    string volumeName,
        //    StringBuilder uniqueVolumeName,
        //    int uniqueNameBufferCapacity);

        //[DllImport("Kernel32.dll", SetLastError = true)]
        //internal static extern IntPtr CreateFile(string lpFileName, int dwDesiredAccess, int dwShareMode, IntPtr lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile);

        //[DllImport("Kernel32.dll", SetLastError = true)]
        //internal static extern bool DeviceIoControl(IntPtr hDevice, int dwIoControlCode, IntPtr lpInBuffer, int nInBufferSize, IntPtr lpOutBuffer, int nOutBufferSize, out int lpBytesReturned, System.Threading.NativeOverlapped lpOverlapped);

        //[DllImport("Kernel32.dll", SetLastError = true)]
        //internal static extern bool CloseHandle(IntPtr hObject);

        // from winerror.h
        internal const int ERROR_NO_MORE_ITEMS = 259;
        internal const int ERROR_INSUFFICIENT_BUFFER = 122;
        internal const int ERROR_INVALID_DATA = 13;

        // from winioctl.h
        internal const string GUID_DEVINTERFACE_VOLUME = "53f5630d-b6bf-11d0-94f2-00a0c91efb8b";
        internal const string GUID_DEVINTERFACE_DISK = "53f56307-b6bf-11d0-94f2-00a0c91efb8b";
        internal const string GUID_DEVINTERFACE_GARMIN = "2C9C45C2-8E7D-4C08-A12D-816BBAE722C0";


        internal const int IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS = 0x00560000;

        [StructLayout(LayoutKind.Sequential)]
        internal struct DISK_EXTENT
        {
            internal int DiskNumber;
            internal long StartingOffset;
            internal long ExtentLength;
        }

        // from cfg.h
        internal enum PNP_VETO_TYPE
        {
            Ok,

            TypeUnknown,
            LegacyDevice,
            PendingClose,
            WindowsApp,
            WindowsService,
            OutstandingOpen,
            Device,
            Driver,
            IllegalDeviceRequest,
            InsufficientPower,
            NonDisableable,
            LegacyDriver,
        }

        //// from cfgmgr32.h
        //[DllImport("setupapi.dll")]
        //internal static extern int CM_Get_Parent(
        //    ref int pdnDevInst,
        //    int dnDevInst,
        //    int ulFlags);

        //[DllImport("setupapi.dll")]
        //internal static extern int CM_Get_Device_ID(
        //    int dnDevInst,
        //    StringBuilder buffer,
        //    int bufferLen,
        //    int ulFlags);

        //[DllImport("setupapi.dll")]
        //internal static extern int CM_Request_Device_Eject(
        //    int dnDevInst,
        //    out PNP_VETO_TYPE pVetoType,
        //    StringBuilder pszVetoName,
        //    int ulNameLength,
        //    int ulFlags
        //    );

        //[DllImport("setupapi.dll", EntryPoint = "CM_Request_Device_Eject")]
        //internal static extern int CM_Request_Device_Eject_NoUi(
        //    int dnDevInst,
        //    IntPtr pVetoType,
        //    StringBuilder pszVetoName,
        //    int ulNameLength,
        //    int ulFlags
        //    );



        // from setupapi.h
        internal const int DIGCF_PRESENT = (0x00000002);
        internal const int DIGCF_DEVICEINTERFACE = (0x00000010);

        internal const int SPDRP_DEVICEDESC = 0x00000000;
        internal const int SPDRP_CAPABILITIES = 0x0000000F;
        internal const int SPDRP_CLASS = 0x00000007;
        internal const int SPDRP_CLASSGUID = 0x00000008;
        internal const int SPDRP_FRIENDLYNAME = 0x0000000C;



        [DllImport("setupapi.dll")]
#if !PocketPC && Framework20
        [SuppressUnmanagedCodeSecurity]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
#endif
        internal static extern IntPtr SetupDiGetClassDevs(
            ref Guid classGuid,
            int enumerator,
            IntPtr hwndParent,
            int flags);

        [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
#if !PocketPC && Framework20
        [SuppressUnmanagedCodeSecurity]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
#endif
        internal static extern bool SetupDiEnumDeviceInterfaces(
            IntPtr deviceInfoSet,
            SP_DEVINFO_DATA deviceInfoData,
            ref Guid interfaceClassGuid,
            int memberIndex,
            SP_DEVICE_INTERFACE_DATA deviceInterfaceData);

        //[DllImport("setupapi.dll")]
        //internal static extern bool SetupDiOpenDeviceInfo(
        //    IntPtr deviceInfoSet,
        //    string deviceInstanceId,
        //    IntPtr hwndParent,
        //    int openFlags,
        //    SP_DEVINFO_DATA deviceInfoData
        //    );

        [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
#if !PocketPC && Framework20
        [SuppressUnmanagedCodeSecurity]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
#endif
        internal static extern bool SetupDiGetDeviceInterfaceDetail(
            IntPtr deviceInfoSet,
            SP_DEVICE_INTERFACE_DATA deviceInterfaceData,
            IntPtr deviceInterfaceDetailData,
            int deviceInterfaceDetailDataSize,
            ref int requiredSize,
            SP_DEVINFO_DATA deviceInfoData);

        [DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
#if !PocketPC && Framework20
        [SuppressUnmanagedCodeSecurity]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
#endif
        internal static extern bool SetupDiGetDeviceRegistryProperty(
            IntPtr deviceInfoSet,
            SP_DEVINFO_DATA deviceInfoData,
            int property,
            out int propertyRegDataType,
            IntPtr propertyBuffer,
            int propertyBufferSize,
            out int requiredSize
            );

        [DllImport("setupapi.dll")]
#if !PocketPC && Framework20
        [SuppressUnmanagedCodeSecurity]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
#endif
        internal static extern uint SetupDiDestroyDeviceInfoList(
            IntPtr deviceInfoSet);

    }
}
#endif